package com.china.produce.postProcess;

import com.china.produce.annotation.DCCValue;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Configuration;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName
 * @Author niujie
 * @Version
 * @Description
 * @CreateTime 2024/12/21
 */
@Configuration
@Slf4j
public class DCCValueBeanFactory implements BeanPostProcessor {

    private static final String BASE_CONFIG_PATH = "/big-market-dcc";

    private static final String BASE_CONFIG_PATH_CONFIG = BASE_CONFIG_PATH + "/config";

    private final CuratorFramework client;

    private final Map<String, Object> maps = new HashMap<>();


    public DCCValueBeanFactory(CuratorFramework zookeeperClients) throws Exception {
        this.client = zookeeperClients;
        if (null == client.checkExists().forPath(BASE_CONFIG_PATH_CONFIG)) {
            client.create().creatingParentsIfNeeded().forPath(BASE_CONFIG_PATH_CONFIG);
        }

        TreeCache treeCache = new TreeCache(client, BASE_CONFIG_PATH_CONFIG);
        TreeCacheListener listener = (client1, event) -> {
            switch (event.getType()) {
                case NODE_UPDATED:
                    String path = event.getData().getPath();
                    Object objBean = maps.get(path);
                    if (null == objBean) return;
                    try {
                        Field field = objBean.getClass().getDeclaredField(path.substring(path.lastIndexOf("/") + 1));
                        field.setAccessible(true);
                        field.set(objBean, new String(event.getData().getData()));
                        field.setAccessible(false);
                    }catch (Exception exception) {
                    }
                default:
                    break;
            }
        };
        treeCache.getListenable().addListener(listener);
        treeCache.start();
    }


    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        Class<?> beanClass = bean.getClass();
        Field[] fields = beanClass.getDeclaredFields();
        for (Field field : fields) {
            if (!field.isAnnotationPresent(DCCValue.class)) continue;
            DCCValue dccValue = field.getAnnotation(DCCValue.class);
            String value = dccValue.value();
            if (StringUtils.isBlank(value)) {
                throw new RuntimeException("dcc value not blank");
            }
            String[] split = value.split(":");
            String key = split[0];
            String defaultValue = split[1];

            try {
                String keyPath = BASE_CONFIG_PATH_CONFIG.concat("/").concat(key);
                if (null == client.checkExists().forPath(keyPath)) {
                    client.create().creatingParentsIfNeeded().forPath(keyPath);
                    if (StringUtils.isNotBlank(defaultValue)) {
                        field.setAccessible(true);
                        field.set(bean, defaultValue);
                        field.setAccessible(false);
                    }
                }else {
                   String configValue = new String(client.getData().forPath(keyPath));
                    if (StringUtils.isNotBlank(configValue)) {
                        field.setAccessible(true);
                        field.set(bean, configValue);
                        field.setAccessible(false);
                    }
                }
                maps.put(keyPath, bean);
            }catch (Exception exception) {

            }
        }

        return bean;
    }
}
